home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1998
/
MacHack 1998.toast
/
The Hacks!
/
MemBuddy
/
SillyBalls.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-16
|
16KB
|
658 lines
// ******************************************************************
// program written by
// Paul Baxter
// MacHack'98
//
// ******************************************************************
#include <A4Stuff.h>
#include <LowMem.h>
#include "membuddy.h"
#define SYS 0x0500 // sys trap attribute
#define eHandleQueType 'HQ' // que types
#define ePtrQueType 'PQ'
typedef struct {
struct QElem *qLink; // next element
short qType; // always kHandleQueType
ProcessSerialNumber process;// process number
Handle theHandle; // Handle
} HandleQElem;
typedef HandleQElem* HandleQElemPtr;
typedef struct {
struct QElem* qLink; // next element
short qType; // always kHandleQueType
ProcessSerialNumber process;// process number
Ptr thePtr; // Pointer
} PtrQElem;
typedef PtrQElem* PtrQElemPtr;
asm void MyNewHandle(void); // the patches
asm void MyNewHandleClear(void);
asm void MyNewPtr(void);
asm void MyNewPtrClear(void);
asm void MyDisposeHandle(void);
asm void MyDisposePtr(void);
// utility functions
void AddHandletoQue(Handle theHandle : __A0);
void RemoveHandleFromQue(Handle theHandle: __A0);
void AddPtrtoQue(Ptr thePtr : __A0);
void RemovePointerFromQue(Ptr thePtr: __A0);
void FreeProcMem(void);
typedef struct { // typedef ques for storing handles and ptrs
QHdr HandleQue;
QHdr PointerQue;
} Ques;
Ptr gOldNewHandle = nil; // old and new trap addresses
Ptr gMyNewHandle = nil;
Ptr gOldNewHandleClear = nil;
Ptr gMyNewHandleClear = nil;
Ptr gOldDisposeHandle = nil;
Ptr gMyDisposeHandle = nil;
Ptr gOldDisposePtr = nil;
Ptr gMyDisposePtr = nil;
Ptr gOldNewPtr = nil;
Ptr gMyNewPtr = nil;
Ptr gOldNewPtrClear = nil;
Ptr gMyNewPtrClear = nil;
long gNumHandles = 0; // num handles we allocated
long gNumPtrs = 0; // num pointers we allocated
Ques gMyQues; // the que header
// flag for internal calls
Boolean gInternalDispose = false;
// ******************************************************************
//
// Main
// main entry point
//
// ******************************************************************
void main(void)
{
Handle myhandle;
EnterCodeResource(); // get globals
// init pointer que
gMyQues.PointerQue.qFlags = 0;
gMyQues.PointerQue.qHead = nil;
gMyQues.PointerQue.qTail = nil;
// init handle que
gMyQues.HandleQue.qFlags = 0;
gMyQues.HandleQue.qHead = nil;
gMyQues.HandleQue.qTail = nil;
// detach ourselves
myhandle = Get1Resource('INIT', 0);
if (myhandle) {
HLock(myhandle);
DetachResource(myhandle);
// install patches
SetTrap(NewHandle);
SetTrap(NewHandleClear);
SetTrap(DisposeHandle);
SetTrap(NewPtr);
SetTrap(NewPtrClear);
SetTrap(DisposePtr);
}
ExitCodeResource();
}
// ******************************************************************
//
// MyNewHandle
// NewHandle patch
//
// ******************************************************************
asm void MyNewHandle(void)
{
Handle newhand; // newly allocated handle
long size; // allocation size
long oldA4; // globals ptr
short trapword; // trap used
fralloc // set stack frame
movem.l D0-D2/A0-A3,-(SP) // save regs
jsr FreeProcMem
movem.l (SP)+,D0-D2/A0-A3 // restore regs
movem.l D1/A1-A3,-(SP) // save regs
move.l D0,size // save size
move.w D1,trapword // save trap word
jsr SetCurrentA4 // set up
move.l D0, oldA4 // globals
move.l size, D0 // fix D0 (size)
movea.l gOldNewHandle,A1 // get old trap address
jsr (A1) // call old routine
tst.w D0 // check for error
beq.s @done // noErr just exit
move.w trapword,D1 // get trap word
cmp.w _NewHandleClear,D1 // _NewHandle = A122
// _NewHandleClear = A322
// _NewHandleSys = A522
// _NewHandleSysClear = A722
bgt.s @done // if system heap don't try again
move.l size,D0 // restore requested size
ori.l #SYS,D1 // set system bit
movea.l gOldNewHandle,A1 // get old trap address
jsr (A1) // call old routine
tst.w D0 // check result
bne @done
move.l A0,newhand // save handle
jsr AddHandletoQue // add it to our que
move.l newhand,A0 // restore result
clr.w D0 // we already know there is no error
@done:
movea.l oldA4,A4 // restore A4
movem.l (SP)+,D1/A1-A3 // restore regs
frfree // unlink stack frame
tst.w D0 // undocumented test for error
rts
}
// ******************************************************************
//
// MyNewHandleClear
// MyNewHandleClear patch
//
// ******************************************************************
asm void MyNewHandleClear(void)
{
Handle newhand; // newly allocated handle
long size; // allocation size
long oldA4; // globals ptr
short trapword; // trap used
fralloc // set stack frame
movem.l D0-D2/A0-A3,-(SP) // save regs
jsr FreeProcMem
movem.l (SP)+,D0-D2/A0-A3 // restore regs
movem.l D1/A1-A3,-(SP) // save regs
move.l D0,size // save size
move.w D1,trapword // save trap word
jsr SetCurrentA4 // set up
move.l D0, oldA4 // globals
move.l size, D0 // fix D0 (size)
// get old trap address
movea.l gOldNewHandleClear,A1
jsr (A1) // call old routine
tst.w D0 // check for error
beq.s @done // noErr just exit
move.w trapword,D1 // get trap word
cmp.w _NewHandleClear,D1 // _NewHandle = A122
// _NewHandleClear = A322
// _NewHandleSys = A522
// _NewHandleSysClear = A722
bgt.s @done // if system heap don't try again
move.l size,D0 // restore requested size
_NewHandleSysClear // try system heap
tst.w D0 // check result
bne @done
move.l A0,newhand // save handle
jsr AddHandletoQue // add it to our que
move.l newhand,A0 // restore result
clr.w D0 // we already know there is no error
@done:
movea.l oldA4,A4 // restore A4
movem.l (SP)+,D1/A1-A3 // restore regs
frfree // unlink stack frame
tst.w D0 // undocumented test for error
rts
}
// ******************************************************************
//
// MyNewPtr
// NewPtr patch
//
// ******************************************************************
asm void MyNewPtr(void)
{
long size; // allocation size
long oldA4; // globals ptr
short trapword; // trap used
Ptr thePtr; // pointer allocated
fralloc // set stack frame
movem.l D0-D2/A0-A3,-(SP) // save regs
jsr FreeProcMem
movem.l (SP)+,D0-D2/A0-A3 // restore regs
move.l D0,size // save size
move.w D1,trapword // save trap word
movem.l D1/A1-A3,-(SP) // save regs
jsr SetCurrentA4 // set up
move.l D0, oldA4 // globals
move.l size,D0 // fix D0 (size)
movea.l gOldNewPtr,A1 // get old trap address
jsr (A1) // call old routine
tst.w D0 // check for error
beq.s @done // noErr just exit
move.w trapword,D1 // get trap word
cmp.w #_NewPtrClear,D1 // _NewPtr = A11E
// _NewPtrClear = A31E
// _NewPtrSys = A51E
// _NewPtrSysClear = A71E
bgt.s @done // if system heap don't try again
move.l size,D0 // restore requested size
ori.l #SYS,D1 // set system bit
movea.l gOldNewPtr,A1 // get old trap address
jsr (A1) // call old routine
tst.w D0 // check result
bne @done
move.l A0,thePtr // save Pointer
jsr AddPtrtoQue // add it to our que
move.l thePtr,A0 // restore result
clr.w D0 // we already know there is no error
@done:
movea.l oldA4,A4 // restore A4
movem.l (SP)+,D1/A1-A3 // restore regs
frfree // unlink stack frame
tst.w D0
rts
}
// ******************************************************************
//
// MyNewPtrClear
// MyNewPtrClear patch
//
// ******************************************************************
asm void MyNewPtrClear(void)
{
long size; // allocation size
long oldA4; // globals ptr
short trapword; // trap used
Ptr thePtr; // pointer allocated
fralloc // set stack frame
movem.l D0-D2/A0-A3,-(SP) // save regs
jsr FreeProcMem
movem.l (SP)+,D0-D2/A0-A3 // restore regs
move.l D0,size // save size
move.w D1,trapword // save trap word
movem.l D1/A1-A3,-(SP) // save regs
jsr SetCurrentA4 // set up
move.l D0, oldA4 // globals
move.l size,D0 // fix D0 (size)
movea.l gOldNewPtr,A1 // get old trap address
jsr (A1) // call old routine
tst.w D0 // check for error
beq.s @done // noErr just exit
move.w trapword,D1 // get trap word
cmp.w #_NewPtrClear,D1 // _NewPtr = A11E
// _NewPtrClear = A31E
// _NewPtrSys = A51E
// _NewPtrSysClear = A71E
bgt.s @done // if system heap don't try again
move.l size,D0 // restore requested size
_NewPtrSysClear // try system heap
tst.w D0 // check result
bne @done
move.l A0,thePtr // save Pointer
jsr AddPtrtoQue // add it to our que
move.l thePtr,A0 // restore result
clr.w D0 // we already know there is no error
@done:
movea.l oldA4,A4 // restore A4
movem.l (SP)+,D1/A1-A3 // restore regs
frfree // unlink stack frame
tst.w D0
rts
}
// ******************************************************************
//
// MyDisposeHandle
// MyDisposeHandle patch
//
// ******************************************************************
asm void MyDisposeHandle(void)
{
long oldA4;
long theHandle;
short trapword;
fralloc // set stack frame
move.l A0,theHandle // save handle
move.w D1,trapword // save trap word
movem.l D0-D2/A0-A3,-(SP) // save regs
jsr RemoveHandleFromQue
movem.l (SP)+,D0-D2/A0-A3 // restore regs
movem.l D1/A1,-(SP) // save regs
jsr SetCurrentA4 // set up globals
move.l D0,oldA4
move.w trapword,D1 // reset trap
move.l theHandle,A0 // reset handle
movea.l gOldDisposeHandle,A1// get old trap address
jsr (A1) // call old routine
movea.l oldA4,A4 // restore A4
movem.l (SP)+,D1/A1 // restore regs
move.l #0,A0
frfree // unlink stack frame
rts
}
// ******************************************************************
//
// MyDisposePtr
// MyDisposePtr patch
//
// ******************************************************************
asm void MyDisposePtr(void)
{
long oldA4;
long thePtr;
short trapword;
fralloc // set stack frame
move.l A0,thePtr
move.w D1,trapword // save trap word
movem.l D0-D2/A0-A3,-(SP) // save regs
jsr RemovePointerFromQue
movem.l (SP)+,D0-D2/A0-A3 // restore regs
movem.l D1/A1,-(SP) // save regs
jsr SetCurrentA4 // set up globals
move.l D0,oldA4
// get old trap address
move.w trapword,D1
move.l thePtr,A0
move.l gOldDisposePtr,A1
jsr (A1) // call old routine
movea.l oldA4,A4 // restore A4
movem.l (SP)+,D1/A1 // restore regs
frfree // unlink stack frame
move.l #0,A0
rts
}
// ******************************************************************
//
// AddHandletoQue
// Add a handle to our handle que
//
// ******************************************************************
void AddHandletoQue(Handle theHandle : __A0)
{
HandleQElemPtr handleQuePtr;
ProcessSerialNumber proc;
OSErr err;
err = GetCurrentProcess(&proc);
if (!err) {
handleQuePtr = (HandleQElemPtr)NewPtrSys(sizeof(HandleQElem));
handleQuePtr->qLink = 0;
handleQuePtr->qType = eHandleQueType;
handleQuePtr->theHandle = theHandle;
BlockMoveData(&proc, &handleQuePtr->process, sizeof(ProcessSerialNumber));
Enqueue((QElem *) handleQuePtr, &gMyQues.HandleQue);
gNumHandles++;
}
}
// ******************************************************************
//
// AddPtrtoQue
// Add a pointer to our pointer que
//
// ******************************************************************
void AddPtrtoQue(Ptr thePtr : __A0)
{
PtrQElemPtr ptrQuePtr;
ProcessSerialNumber proc;
OSErr err;
err = GetCurrentProcess(&proc);
if (!err) {
ptrQuePtr = (PtrQElemPtr)NewPtrSys(sizeof(PtrQElem));
ptrQuePtr->qLink = 0;
ptrQuePtr->qType = ePtrQueType;
ptrQuePtr->thePtr = thePtr;
BlockMoveData(&proc, &ptrQuePtr->process, sizeof(ProcessSerialNumber));
Enqueue((QElem *) ptrQuePtr, &gMyQues.PointerQue);
gNumPtrs++;
}
}
// ******************************************************************
//
// FreeProcMem
// free memmory if appropriate
//
// ******************************************************************
void FreeProcMem(void)
{
ProcessInfoRec procInfo;
Str255 name;
FSSpec appSpec;
HandleQElemPtr handleQuePtr;
PtrQElemPtr ptrQuePtr;
unsigned long size;
OSErr err;
short resflags;
Boolean found;
EnterCodeResource();
gInternalDispose = true;
if ((gNumHandles > 0 || gNumPtrs > 0)) {
// kill handles
do {
found = true;
handleQuePtr = (HandleQElemPtr) gMyQues.HandleQue.qHead;
while (handleQuePtr) {
procInfo.processInfoLength = sizeof(ProcessInfoRec);
procInfo.processName = name;
procInfo.processAppSpec = &appSpec;
err = GetProcessInformation(&handleQuePtr->process,&procInfo);
found = (err == noErr);
// see if the process is still running
if (!found) {
// check resource attribute
resflags = GetResAttrs(handleQuePtr->theHandle);
if (ResError()) {
size = GetHandleSize(handleQuePtr->theHandle);
if (size) {
HUnlock(handleQuePtr->theHandle);
HPurge(handleQuePtr->theHandle);
DisposeHandle(handleQuePtr->theHandle);
}
}
Dequeue((QElem *)handleQuePtr, &gMyQues.HandleQue);
gNumHandles--;
DisposePtr((Ptr)handleQuePtr);
// DO NOT ZERO OUT handleQuePtr
break;
}
handleQuePtr = (HandleQElemPtr) handleQuePtr->qLink;
}
} while (!found);
// Kill Pointers
do {
found = true;
ptrQuePtr = (PtrQElemPtr) gMyQues.PointerQue.qHead;
while (ptrQuePtr) {
procInfo.processInfoLength = sizeof(ProcessInfoRec);
procInfo.processName = name;
procInfo.processAppSpec = &appSpec;
err = GetProcessInformation(&ptrQuePtr->process, &procInfo);
found = (err == noErr);
// see if the process is still running
if (!found) {
size = GetPtrSize(ptrQuePtr->thePtr);
if (size) {
DisposePtr(ptrQuePtr->thePtr);
}
Dequeue((QElem *)ptrQuePtr, &gMyQues.PointerQue);
gNumPtrs--;
DisposePtr((Ptr)ptrQuePtr);
// DO NOT ZERO OUT ptrQuePtr
break;
}
ptrQuePtr = (PtrQElemPtr) ptrQuePtr->qLink;
}
} while (!found);
}
gInternalDispose = false;
ExitCodeResource();
}
// ******************************************************************
//
// RemovePointerFromQue
// remove a pointer from the pointer que
//
// ******************************************************************
void RemovePointerFromQue(Ptr thePointer: __A0)
{
PtrQElemPtr ptrQuePtr;
EnterCodeResource();
if (gInternalDispose) {
ExitCodeResource();
return;
}
ptrQuePtr = (PtrQElemPtr) gMyQues.PointerQue.qHead;
while (ptrQuePtr) {
if (ptrQuePtr->thePtr == thePointer) {
Dequeue((QElem *)ptrQuePtr, &gMyQues.PointerQue);
gNumPtrs --;
DisposePtr((Ptr)ptrQuePtr);
break;
}
ptrQuePtr = (PtrQElemPtr) ptrQuePtr->qLink;
}
ExitCodeResource();
FreeProcMem();
}
// ******************************************************************
//
// RemoveHandleFromQue
// remove a handle from the handle que
//
// ******************************************************************
void RemoveHandleFromQue(Handle theHandle: __A0)
{
HandleQElemPtr handleQuePtr;
EnterCodeResource();
if (gInternalDispose) {
ExitCodeResource();
return;
}
handleQuePtr = (HandleQElemPtr) gMyQues.HandleQue.qHead;
while (handleQuePtr) {
if (handleQuePtr->theHandle == theHandle) {
Dequeue((QElem *)handleQuePtr, &gMyQues.HandleQue);
gNumHandles--;
DisposePtr((Ptr)handleQuePtr);
break;
}
handleQuePtr = (HandleQElemPtr) handleQuePtr->qLink;
}
ExitCodeResource();
FreeProcMem();
}